import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;

import javax.imageio.ImageIO;


@SuppressWarnings("serial")
public class TicTacToePanel extends JPanel implements MouseListener, Game
{
	BufferedImage Xs, Os;
	int[][] TTT;
	int size, playerType, id, winner;
	int spread;
	boolean isTurn, isComplete;
	GamePanel gamePanel;
	String username;
	
	public TicTacToePanel(int id, GamePanel game)
	{
		this.id = id;
		playerType = 1;
		isTurn = true;
		isComplete = false;
		winner = 0;
		gamePanel = game;
		addMouseListener(this);
		try 
		{
			Xs = ImageIO.read(new File("TTT-X.png"));
			Os = ImageIO.read(new File("TTT-O.png"));
		} catch (IOException e) 
		{
			System.out.println("File not found");
		}
		
		TTT = new int[3][3];
	}
	
	public TicTacToePanel(int id, String user, GamePanel game)
	{
		this(id, game);
		username = user;
		playerType = -1;
		isTurn = false;
	}

	public void paint(Graphics g)
	{
		isComplete = checkDone();
		int width = getWidth();
		int height = getHeight();
		g.setColor(Color.white);
		g.fillRect(0, 0, width, height);
		g.setColor(Color.black);
		if(isComplete)
		{
			height -= 50;
			g.setFont(g.getFont().deriveFont(20.0F));
			int strWid = g.getFontMetrics().stringWidth("Game Over");
			g.drawString("Game Over", (width - strWid) / 2, height + 20);
			String outcome = "Draw";
			if(winner == playerType)
				outcome = "You Won!";
			if(winner == -playerType)
				outcome = "You Lost.";
			strWid = g.getFontMetrics().stringWidth(outcome);
			g.drawString(outcome, (width - strWid) / 2, height + 45);
		}
		size = Math.min(width, height);
		spread = 0;
		if(width != size)
		{
			spread = width - size;
			spread /= 2;
		}
		size /= 3;
		int divider = size / 10;
		
		int hei = divider/2;
		
		for(int[] i : TTT)
		{
			int wid = divider/2 + spread;
			for(int XO : i)
			{
				if(XO == 1)
					g.drawImage(Xs, wid, hei, size-divider, size-divider, null);
				if(XO == -1)
					g.drawImage(Os, wid, hei, size-divider, size-divider, null);
				wid += size;
			}
			hei += size;
		}
		g.setColor(Color.black);
		for(int i = 1; i < 3; i++)
		{
			g.fillRect(size * i - divider/2 + spread, 0, divider, size*3);
			g.fillRect(spread, size * i - divider/2, size*3, divider);
		}
	}
	
	public int getID()
	{
		return id;
	}
	
	public void playerTurn()
	{
		isComplete = checkDone();
		if(!isComplete)
			isTurn = true;
	}
	
	private boolean checkDone() 
	{
		boolean exists = true;
		for(int i = 0; i < 3 && exists; i++)
			for(int j = 0; j < 3; j++)
				if(TTT[i][j] == 0)
					exists = false;
		if(exists)
		{
			winner = 0;
			return true;
		}
		int tot1 = 0, tot2 = 0, tot3 = 0;
		int tot4 = 0, tot5 = 0, tot6 = 0;
		for(int i  = 0; i < 3; i++)
		{
			tot1 += TTT[0][i];
			tot2 += TTT[1][i];
			tot3 += TTT[2][i];
			tot4 += TTT[i][0];
			tot5 += TTT[i][1];
			tot6 += TTT[i][2];
		}
		if(tot1 == 3 || tot2 == 3 || tot3 == 3 || tot4 == 3 || tot5 == 3 || tot6 == 3)
		{
			winner = 1;
			return true;
		}
		if(tot1 == -3 || tot2 == -3 || tot3 == -3 || tot4 == -3 || tot5 == -3 || tot6 == -3)
		{
			winner = -1;
			return true;
		}
		if(TTT[1][1] != 0)
		{
			if(TTT[0][0] == TTT[1][1] && TTT[1][1] == TTT[2][2])
			{
				winner = TTT[1][1];
				return true;
			}
			if(TTT[2][0] == TTT[1][1] && TTT[1][1] == TTT[0][2])
			{
				winner = TTT[1][1];
				return true;
			}
		}
		return false;
	}

	public void refresh(char[] arr)
	{
		for(int i = 0; i < arr.length; i++)
		{
			System.out.print(arr[i] + "  ");
			int val = 0;
			if(arr[i] == 'X')
				val = 1;
			if(arr[i] == 'O')
				val = -1;
			int x = i/3;
			int y = i%3;
			TTT[x][y] = val;
		}
		SwingUtilities.invokeLater(new Runnable()
		{
			@Override
			public void run() 
			{
				repaint();
			}
		});
	}
	
	public char[] array()
	{
		System.out.println("Executed");
		char[] ret = new char[9];
		for(int i = 0; i < 3; i++) { 
			for(int j = 0; j < 3; j++) {
				char car = ' ';
				if(TTT[i][j] == 1)
					car = 'X';
				if(TTT[i][j] == -1)
					car = 'O';
				ret[i*3 + j] = car;
			}
		}
		System.out.println(Arrays.deepToString(TTT));
		return ret;
	}

	@Override
	public void mouseClicked(MouseEvent e) 
	{
		if(isTurn && !isComplete)
		{
			Point pt = e.getPoint();
			int x = (pt.x - spread);
			if(x >= 0)
			{
				x /= size;
				int y = pt.y / size;
				if(x < 3 && y < 3 && TTT[y][x] == 0)
				{
					TTT[y][x] = playerType;
					repaint();
					gamePanel.sendData(id, username, array());
					isTurn = false;
				}
			}
		}
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {}
	@Override
	public void mouseExited(MouseEvent arg0) {}
	@Override
	public void mousePressed(MouseEvent arg0) {}
	@Override
	public void mouseReleased(MouseEvent arg0) {}

	@Override
	public void setID(int val) 
	{
		id = val;
	}
}
